package com.wolf.antlr;

import com.wolf.antlr.c.CBaseListener;
import com.wolf.antlr.c.CLexer;
import com.wolf.antlr.c.CParser;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CSearcher {
    static List<MethodFragment> searchFunctions(String fileName, CListenerImp listener) {
        Lexer lexer;
        try {
            lexer = new CLexer(CharStreams.fromFileName(fileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        TokenStream tokenStream = new CommonTokenStream(lexer);
        CParser parser = new CParser(tokenStream);
        ParseTree tree = parser.translationUnit();
        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(listener, tree);
        return listener.getMethodFragments();
    }

    public static void main(String[] args) {
        CListenerImp listener = new CListenerImp();
        String fileName = Main.parserArgs(args, listener);
        List<MethodFragment> methodFragments = searchFunctions(fileName, listener);
        methodFragments.forEach(methodFragment -> System.out.printf("%s, %s, %s, %s, %s\n",
                methodFragment.startIndex(),
                methodFragment.endIndex(),
                methodFragment.startLine(),
                methodFragment.endLine(),
                methodFragment.methodDeclaration()));
    }

    static class CListenerImp extends CBaseListener implements IListener {
        private String getMethodDeclaration(CParser.FunctionDefinitionContext ctx) {
            StringBuilder func_del = new StringBuilder();
            // 获取DeclarationSpecifiersContext对象
            CParser.DeclarationSpecifiersContext declarationSpecifiers = ctx.declarationSpecifiers();

            func_del.append(declarationSpecifiers.getText()).append(" ");
            // 获取DeclaratorContext对象
            CParser.DeclaratorContext declarator = ctx.declarator();
            CParser.DirectDeclaratorContext directDeclarator = declarator.directDeclarator();

            func_del.append(directDeclarator.start.getText());


            // 判断是否是函数声明
            List<String> paras = new ArrayList<>();
            if (directDeclarator.directDeclarator() != null && directDeclarator.parameterTypeList() != null) {
                // 获取ParameterListContext对象
                CParser.ParameterListContext parameterList = directDeclarator.parameterTypeList().parameterList();
                // 遍历参数列表
                for (CParser.ParameterDeclarationContext parameterDeclaration : parameterList.parameterDeclaration()) {
                    // 获取DeclarationSpecifiersContext对象
                    if (parameterDeclaration.declarationSpecifiers() != null) {
                        List<CParser.DeclarationSpecifierContext> dec_Spes = parameterDeclaration.declarationSpecifiers().declarationSpecifier();
                        List<String> modifiers = new ArrayList<>();
                        for (CParser.DeclarationSpecifierContext dec_Spe : dec_Spes
                        ) {
                            // Get the TypeSpecifierContext object
                            if (dec_Spe.typeSpecifier() != null) {
                                CParser.TypeSpecifierContext tsc = dec_Spe.typeSpecifier();
                                // Check if the type specifier is a struct or union specifier
                                if (tsc.structOrUnionSpecifier() != null) {
                                    // Get the StructOrUnionSpecifierContext object
                                    CParser.StructOrUnionSpecifierContext susc = tsc.structOrUnionSpecifier();
                                    // Get the text of the struct or union specifier, which is the struct type of the parameter
                                    String structType = susc.structOrUnion().getText() + " " + susc.Identifier().getText();
                                    // Print the struct type
                                    modifiers.add(structType);
                                } else modifiers.add(tsc.getText());
                            }
                        }
                        // 获取DeclaratorContext对象
                        CParser.DeclaratorContext dec = parameterDeclaration.declarator();
                        // 提取参数类型和名称
                        String parameterName = dec.getText();
                        // 输出或保存参数类型和名称
                        paras.add(String.join(" ", modifiers) + " " + parameterName);
                    }

                }
            }
            func_del.append("(");
            func_del.append(String.join(", ", paras));
            func_del.append(")");


            System.out.println(func_del);
            return func_del.toString();

        }

        @Override
        public void enterFunctionDefinition(CParser.FunctionDefinitionContext ctx) {
            super.enterFunctionDefinition(ctx);
            String methodDeclaration = this.getMethodDeclaration(ctx);
            this.searchByLine(ctx, methodDeclaration);
            this.searchByDeclaration(ctx, methodDeclaration);
        }
    }
}
